/**
 * @file CompactProtocol.cpp
 * @brief 紧凑型二进制协议实现
 * @author Your Name
 * @date 2025-03-30
 */

#include "compactprotocol.h"
#include <QDebug>
#include <QMutexLocker>

CompactProtocol::CompactProtocol(QObject *parent) : IProtocol(parent) {
    // 预分配接收缓冲区，减少动态分配开销
    m_buffer.reserve(1024);
}

QByteArray CompactProtocol::encodePacket(uint8_t cmdType, const QByteArray& data) {
    QByteArray packet;

    // 确保数据长度不超过255
    if (data.size() > 255) {
        qWarning() << "数据长度超出协议限制: " << data.size();
        emit protocolError(Protocol::ERR_LENGTH, "数据长度超出协议限制");
        return packet;
    }

    // 帧头 (2字节)
    packet.append((Protocol::FRAME_HEADER >> 8) & 0xFF);
    packet.append(Protocol::FRAME_HEADER & 0xFF);

    // 命令码 (1字节)
    packet.append(cmdType);

    // 数据长度 (1字节)
    packet.append(static_cast<char>(data.size()));

    // 数据体
    if (!data.isEmpty()) {
        packet.append(data);
    }

    // 校验码 (对除帧头外的所有字节进行异或)
    QByteArray checksumData = packet.mid(2); // 跳过帧头
    uint8_t checksum = calculateChecksum(checksumData);
    packet.append(static_cast<char>(checksum));

    return packet;
}

void CompactProtocol::parseReceivedData(const QByteArray& recvData) {
    if (recvData.isEmpty()) {
        return;
    }

    // 线程安全地追加数据到缓冲区
    {
        QMutexLocker locker(&m_mutex);
        m_buffer.append(recvData);
    }

    // 循环解析所有可能的完整数据包
    QMutexLocker locker(&m_mutex);

    while (m_buffer.size() >= Protocol::FRAME_MIN_LEN) {
        // 查找帧头
        int headerPos = findFrameHeader(m_buffer, 0);
        if (headerPos < 0) {
            // 未找到帧头，清空缓冲区
            m_buffer.clear();
            break;
        }

        // 如果帧头不在起始位置，清除前面的无效数据
        if (headerPos > 0) {
            m_buffer.remove(0, headerPos);
        }

        // 检查是否能读取完整的帧长度字段
        if (m_buffer.size() < Protocol::HEADER_LEN + Protocol::CMD_LEN + Protocol::LEN_FIELD_LEN) {
            // 数据不足，等待更多数据
            break;
        }

        // 获取数据长度
        uint8_t dataLen = static_cast<uint8_t>(m_buffer.at(Protocol::HEADER_LEN + Protocol::CMD_LEN));

        // 计算完整包长度
        int packetLen = Protocol::HEADER_LEN + Protocol::CMD_LEN + Protocol::LEN_FIELD_LEN + dataLen + Protocol::CHECKSUM_LEN;

        // 检查缓冲区是否有完整包
        if (m_buffer.size() < packetLen) {
            // 数据不足，等待更多数据
            break;
        }

        // 截取完整数据包
        QByteArray packet = m_buffer.mid(0, packetLen);

        // 从缓冲区移除已处理的包
        m_buffer.remove(0, packetLen);

        // 解析这个包
        parsePacket(packet);
    }
}

uint8_t CompactProtocol::calculateChecksum(const QByteArray& data) const {
    uint8_t checksum = 0;

    // 对所有字节执行异或操作
    for (char byte : data) {
        checksum ^= static_cast<uint8_t>(byte);
    }

    return checksum;
}

void CompactProtocol::parsePacket(const QByteArray& packet) {
    // 验证包长度
    if (packet.size() < Protocol::FRAME_MIN_LEN) {
        emit protocolError(Protocol::ERR_LENGTH, "数据包长度不足");
        return;
    }

    // 验证校验和
    uint8_t receivedChecksum = static_cast<uint8_t>(packet.at(packet.size() - 1));// 提取检验和
    QByteArray checksumData = packet.mid(2, packet.size() - 3); // 跳过帧头（2字节）和校验位（1字节）
    uint8_t calculatedChecksum = calculateChecksum(checksumData);   // 计算校验和

    // 比对校验
    if (receivedChecksum != calculatedChecksum) {
        emit protocolError(Protocol::ERR_CHECKSUM, "校验和错误");
        return;
    }

    // 提取命令码
    uint8_t cmdType = static_cast<uint8_t>(packet.at(2));

    // 提取数据部分
    uint8_t dataLen = static_cast<uint8_t>(packet.at(3));
    QByteArray data;

    if (dataLen > 0) {
        data = packet.mid(4, dataLen);
    }

    // 发送解析成功信号
    emit packetParsed(cmdType, data);
}

int CompactProtocol::findFrameHeader(const QByteArray& data, int startPos) const {
    // 帧头为两字节 0xAA55
    for (int i = startPos; i < data.size() - 1; ++i) {
        if ((static_cast<uint8_t>(data.at(i)) == ((Protocol::FRAME_HEADER >> 8) & 0xFF)) &&
            (static_cast<uint8_t>(data.at(i + 1)) == (Protocol::FRAME_HEADER & 0xFF))) {
            return i;
        }
    }
    return -1;
}
